/****************************************************************************
 * Copyright (C) 2025 Chenyz. All rights reserved.
 *
 * @file    TinyOS_Bitmap.c
 *
 * @par     dependencies
 *          - TinyOS_Lib.h
 *
 * @author  Chenyz
 *
 * @brief   Bitmap manipulation module for TinyOS with following features:
 *          - Efficient bit-level operations for resource management
 *          - Fast bit position finding using lookup table
 *          - Boundary checking for safe operations
 *          - Support for bit set, clear and query operations
 *          - Hardware-agnostic design for portability
 *          - Cross-platform compatibility (bare-metal/RTOS systems)
 *
 * @version V1.0
 * @date    2025-05-23
 *
 * @note    Coding standard:
 *          - 4 spaces per indent level
 *          - Follow MISRA-C 2012 guidelines
 *          - Compiler compatibility: C99 and above
 *
 ****************************************************************************/

#include "TinyOS_Lib.h"

/**
 * @brief Initializes a bitmap structure
 * 
 * This function sets all bits in the bitmap to zero, preparing it for use.
 * 
 * @param Bitmap Pointer to the bitmap structure to be initialized
 */
void TinyOS_BitmapInit(TinyOS_BitmapType* Bitmap)
{
    Bitmap->BitmapData = (uint32_t)0UL;
}

/**
 * @brief Clears a specific bit in the bitmap
 * 
 * This function clears (sets to 0) the bit at the specified position
 * in the bitmap, with bounds checking to prevent out-of-range access.
 * 
 * @param Bitmap Pointer to the bitmap structure
 * @param Position Bit position to clear (0-based index)
 */
void TinyOS_BitmapClear(TinyOS_BitmapType* Bitmap, uint32_t Position)
{
    if(Position > TinyOS_BitmapDataLength(Bitmap))
    {
        /* Position is out of range - do nothing */
        return;
    }
    Bitmap->BitmapData &= ~(1UL << Position);
}

/**
 * @brief Sets a specific bit in the bitmap
 * 
 * This function sets (to 1) the bit at the specified position
 * in the bitmap, with bounds checking to prevent out-of-range access.
 * 
 * @param Bitmap Pointer to the bitmap structure
 * @param Position Bit position to set (0-based index)
 */
void TinyOS_BitmapSet(TinyOS_BitmapType* Bitmap, uint32_t Position)
{
    if(Position > TinyOS_BitmapDataLength(Bitmap))
    {
        /* Position is out of range - do nothing */
        return;
    }
    Bitmap->BitmapData |= (1UL << Position);
}

/**
 * @brief Finds the position of the first set bit in the bitmap
 * 
 * This function uses a lookup table to quickly find the position
 * of the first set bit (least significant bit) in the bitmap.
 * 
 * @param Bitmap Pointer to the bitmap structure
 * @return uint32_t Position of the first set bit (0-31), or 0xFF if no bits are set
 */
uint32_t TinyOS_BitmapGetFirstBit(TinyOS_BitmapType* Bitmap)
{
    /* Lookup table for fast bit position finding */
    static const uint8_t QuickFindTable[] = 
    {
        /* 00 */ 0xff, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 10 */ 4,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 20 */ 5,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 30 */ 4,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 40 */ 6,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 50 */ 4,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 60 */ 5,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 70 */ 4,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 80 */ 7,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 90 */ 4,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* A0 */ 5,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* B0 */ 4,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* C0 */ 6,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* D0 */ 4,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* E0 */ 5,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* F0 */ 4,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
    };
    
    /* Check each byte of the 32-bit value from LSB to MSB */
    if(Bitmap->BitmapData & 0xFF)
    {
        /* First set bit is in the least significant byte */
        return QuickFindTable[(Bitmap->BitmapData & 0xFF)];
    }
    else if((Bitmap->BitmapData >> 8) & 0xFF)
    {
        /* First set bit is in the second byte */
        return QuickFindTable[((Bitmap->BitmapData >> 8) & 0xFF)] + 8;
    }
    else if((Bitmap->BitmapData >> 16) & 0xFF)
    {
        /* First set bit is in the third byte */
        return QuickFindTable[((Bitmap->BitmapData >> 16) & 0xFF)] + 16;
    }
    else if((Bitmap->BitmapData >> 24) & 0xFF)
    {
        /* First set bit is in the most significant byte */
        return QuickFindTable[((Bitmap->BitmapData >> 24) & 0xFF)] + 24;
    }
    else
    {
        /* No bits are set in the bitmap */
        return 0xFF;
    }   
}

/**
 * @brief Returns the length (in bits) of the bitmap data
 * 
 * This function calculates the number of bits that can be stored
 * in the bitmap based on its underlying data type size.
 * 
 * @param Bitmap Pointer to the bitmap structure
 * @return uint32_t Number of bits in the bitmap
 */
uint32_t TinyOS_BitmapDataLength(TinyOS_BitmapType* Bitmap)
{
    return (sizeof(Bitmap->BitmapData) * 8);
}

